package com.mccken.rapid.core.context;

import com.mccken.rapid.common.util.AssertUtil;

import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

/**
 * @program: rapid_gateway
 * @description:
 * @author: mccken
 * @create: 2022-01-19 22:49
 **/
public class RapidContext extends BasicContext {
	
	private final RapidRequest rapidRequest;
	
	private RapidResponse rapidResponse;
	
	private final Rule rule;

	private RapidContext(String protocol, ChannelHandlerContext nettyCtx, boolean keepAlive,
			RapidRequest rapidRequest, Rule rule) {
		super(protocol, nettyCtx, keepAlive);
		this.rapidRequest = rapidRequest;
		this.rule = rule;
	}
	
	public static class Builder {
		private String protocol;
		private ChannelHandlerContext nettyCtx;
		private boolean keepAlive;
		private RapidRequest rapidRequest; 
		private Rule rule;
		
		public Builder(){}
		
		public Builder setProtocol(String protocol) {
			this.protocol = protocol;
			return this;
		}

		public Builder setNettyCtx(ChannelHandlerContext nettyCtx) {
			this.nettyCtx = nettyCtx;
			return this;
		}

		public Builder setRapidRequest(RapidRequest rapidRequest) {
			this.rapidRequest = rapidRequest;
			return this;
		}

		public Builder setRule(Rule rule) {
			this.rule = rule;
			return this;
		}

		public Builder setKeepAlive(boolean keepAlive) {
			this.keepAlive = keepAlive;
			return this;
		}

		public RapidContext build() {
			AssertUtil.notNull(protocol, "protocol不能为空");
			AssertUtil.notNull(nettyCtx, "nettyCtx不能为空");
			AssertUtil.notNull(rapidRequest, "rapidRequest不能为空");
			AssertUtil.notNull(rule, "rule不能为空");
			return new RapidContext(protocol, nettyCtx, keepAlive, rapidRequest, rule);
		}
	}
	
	// 获取必要的上下文参数，如果没有则抛出异常
	public <T> T getRequiredAttribute(AttributeKey<T> key) {
		T value = getAttribute(key);
		AssertUtil.notNull(value, "required attribute '" + key + "' is missing !");
		return value;
	}
	
	public <T> T getAttributeOrDefault(AttributeKey<T> key, T defaultValue){
		return (T) attributes.getOrDefault(key,defaultValue);
	}
	
	public Rule.FilterConfig getFilterConfig(String filterId) {
		return rule.getFilterConfig(filterId);
	}
	
	public String getUniqueId() {
		return rapidRequest.getUniqueId();
	}

	public RapidRequest getRequestMutale() {
		return rapidRequest;
	}

	// 调用该方法就是获取原始请求内容，不去做任何修改动作
	public RapidRequest getOriginRequest() {
		return rapidRequest;
	}
	
	@Override
	public void releaseRequest() {
		if (requestReleased.compareAndSet(false,true)) {
			ReferenceCountUtil.release(rapidRequest.getFullHttpRequest());
		}
	}

	@Override
	public Rule getRule() {
		return this.rule;
	}

	@Override
	public Object getRequest() {
		return this.rapidRequest;
	}

	@Override
	public Object getResponse() {
		return this.rapidResponse;
	}

	@Override
	public void setResponse(Object response) {
		this.rapidResponse = (RapidResponse) response;
	}
}
